#include "SemanticHandler/RDFSProcessor/structure/Term.h"  // 基本的元素
#include "SemanticHandler/RDFSProcessor/structure/Predicate.h" //三元体查询
#include "SemanticUtil/Binding.h" //答案的单个绑定
#include "SemanticUtil/NTuple.h"  //多个绑定组成的答案
#include "Statement.h"  //实际存储的语句
#include "SemanticHandler/RDFSProcessor/RDFSUtil.h"   //获取triplePattern2Predicate
#include <vector>
#include <list>
#include <string>
#include <iostream>
#include <QtCore>
#include <QtCore/QList>

#ifndef _FWDRULE_H_
#define _FWDRULE_H_
class FwdRule{
public:

	FwdRule();
	~FwdRule();
	FwdRule(const FwdRule& other);
	FwdRule& operator=(const FwdRule& other); //浅复制
	QList<Predicate> getPreconditions();

    /**
     * Bind this rule to a specific Statement.
     *
     * The purpose of this method is to allow retricting the application of
     * a rule to one statement, i.e. a newly added one.
     *
     * \param statement The Statement to bind this rule to.
     *
     * \sa createSparqlQuery, bindEffect, bindPreconditions
     */
    void bindToStatement(Statement statement );



    /**
     * Add a precondition
     */
    void addPrecondition( Predicate );
    /**
     * The effect of a rule is a pattern that repeats variables from
     * the preconditions and thus, identifies the statements that
     * are to be infered from the preconditions.
     */
    Predicate getEffect();
    /**
     * Set the effect of the rule.
     */
    void setEffect(Predicate );

    /**
     * Create a SPARQL query that retrieves all resources matching this rule.
     *
     * \param bindVariables If true and a valid binding statement is set the query
     * will be bound to this statement resulting in a UNION query of all possible
     * bindings.
     *
     * \return A full SPARQL query or an empty string if this rule does not apply
     * to the statement set via bindToStatement.
     *
     * \sa bindToStatement
     */
    QString createSparqlQuery( bool bindVariables = false );

    /**
     * Bind the rule's effect to a set of bindings as reveived from a query.
     * If the bindings do not contain all variables the bound statement is used as backup.
     *
     * \param bindings The bindings to apply to this rule.
     *
     * \return The statement infered by this rule under the application of bindings.
     *
     * \sa bindToStatement, bindPreconditions
     */
    Statement bindEffect(NTuple bindings );


    /**
     * Bind the rule's preconditions to a set of bindings as reveived from a query.
     * If the bindings do not contain all variables the bound statement is used as backup.
     *
     * \param bindings The bindings to apply to this rule.
     *
     * \return The statements that have to be valid in order for this rule to infer the statement
     * returned by bindEffect under the same bindings.
     *
     * \sa bindToStatement, bindEffect
     */
    QList<Statement> bindPreconditions(NTuple bindings );


    /**
     * Check if a statement matches any of the statement patterns
     * in this rule.
     *
     * \return true if statement matches any of the patterns, false otherwise.
     * Be aware that createSparqlQuery() might still return an empty string
     * since it does perform some aditional optimization checks based on the
     * bound statement.
     */
    bool match(Statement statement );


    /**
     * Check if a rule is valid.
     *
     * \return \p true if the rule is valid and can be used with the InferenceModel,
     * \p false otherwise.
     *
     * \since 2.3
     */
    bool isValid() const;

    std::string toString();

    /**
     * \return The statement set ia bindToStatement() or
     * an invalid one if none was set.
     */
    Statement getBoundToStatement();

public:
    /**
     * Merges in binding information from the bindingStatement by matching it to the preconditions.
     * This is necessary for optimized queries.
     */
	NTuple mergeBindingStatement( NTuple bindings );
	Statement bindStatementPattern(Predicate pattern,NTuple bindings );

public:
    QList<Predicate> preconditions;
    Predicate effect;
    Statement bindingStatement;
};
#endif
